#include "bglCamera.h"

glm::mat4 BGLCamera::CreatePerspective(float fieldOfView, float aspectRatio, float zNearPlane, float zFarPlane)
{
    return glm::perspective(fieldOfView, aspectRatio, zNearPlane, zFarPlane);
}

glm::mat4 BGLCamera::CreateLookAt(const glm::vec3& eyePosition, const glm::vec3& targetPosition, const glm::vec3& up)
{
    return glm::lookAt(eyePosition, targetPosition, up);
}

glm::vec3 BGLCamera::World2Screen(const glm::vec3& obj, const glm::mat4& model, const glm::mat4& proj, const glm::vec4& viewport)
{
    return glm::project(obj, model, proj, viewport);
}

glm::vec3 BGLCamera::Screen2World(const glm::vec3& win, const glm::mat4& model, const glm::mat4& proj, const glm::vec4& viewport)
{
    return glm::unProject(win, model, proj, viewport);
}

/******************************************************************************************************************************************/

BGLCamera::BGLCamera()
    :
    m_fieldOfView   (glm::radians(60.f)),
    m_nearPlane     (0.01f),
    m_farPlane      (1500.f),
    m_eye           (glm::vec3(0, 0, 6)),
    m_target        (glm::vec3(0, 0, 0)),
    m_up            (glm::vec3(0, 1, 0)),
    m_rotation      (glm::vec3(0, 0, 0)),
    m_worldRotation (glm::vec3(0, 0, 0))
{
}

BGLCamera::~BGLCamera()
{
}

void BGLCamera::InitCamera(const float screenWidth, const float screenHieght)
{
    m_screenWidth = screenWidth;
    m_screenHeight = screenHieght;
    Update();
}

void BGLCamera::SetPosition(const glm::vec3& position)
{
    m_eye = position;
    Update();
}

void BGLCamera::SetRotation(const glm::vec3& rotation)                    //设置相机旋转角度
{
    m_rotation = rotation;
    Update();
}

void BGLCamera::SetTargetPosition(const glm::vec3& position)
{
    m_target = position;
    Update();
}

void BGLCamera::SetFieldOfView(const float fieldOfView)
{
    m_fieldOfView = fieldOfView;
    Update();
}

void BGLCamera::SetScreenWidth(const float screenWidth)
{
    m_screenWidth = screenWidth;
    Update();
}

void BGLCamera::SetScreenHeight(const float screenHeight)
{
    m_screenHeight = screenHeight;
    Update();
}

void BGLCamera::SetNearPlane(const float nearPlane)
{
    m_nearPlane = nearPlane;
    Update();
}

void BGLCamera::SetFarPlane(const float farPlane)
{
    m_farPlane = farPlane;
    Update();
}

void BGLCamera::Translate (const glm::vec3& position)
{
    m_eye += position;
    Update();
}

void BGLCamera::TargetTranslate(const glm::vec3& position)
{
    m_target += position;
    Update();
}

void BGLCamera::Rotate(const glm::vec3& delta)
{
    m_rotation += delta;
    Update();
}

void BGLCamera::Update()
{
    glm::mat4 rotM  = glm::mat4(1.0f);  //本身旋转
    glm::mat4 rotW  = glm::mat4(1.0f);  //世界旋转
    glm::mat4 trans = glm::mat4(1.0f);

    rotM = glm::rotate(rotM, glm::radians(m_rotation.x), glm::vec3(1.0f, 0.0f, 0.0f));
    rotM = glm::rotate(rotM, glm::radians(m_rotation.y), glm::vec3(0.0f, 1.0f, 0.0f));
    rotM = glm::rotate(rotM, glm::radians(m_rotation.z), glm::vec3(0.0f, 0.0f, 1.0f));

    // rotW = glm::translate(rotW, m_target);
    rotW = glm::rotate(rotW, glm::radians(m_worldRotation.x), glm::vec3(1.0f, 0.0f, 0.0f));
    rotW = glm::rotate(rotW, glm::radians(m_worldRotation.y), glm::vec3(0.0f, 1.0f, 0.0f));
    rotW = glm::rotate(rotW, glm::radians(m_worldRotation.z), glm::vec3(0.0f, 0.0f, 1.0f));

    m_view    = this->CreateLookAt(m_eye, m_target, m_up);     //视图矩阵
    m_project = this->CreatePerspective(m_fieldOfView, m_screenWidth / m_screenHeight, m_nearPlane, m_farPlane);   //观察矩阵

    //m_view = rotM * m_view;  //绕自身坐标轴旋转
    m_view = rotM * m_view * rotW;  //绕自身坐标轴与世界坐标
}

void BGLCamera::SetRotationOfWorld(const glm::vec3& rotation)
{
    m_worldRotation = rotation;
    Update();
}

void BGLCamera::RotationOfWorld(const glm::vec3& delta)
{
    m_worldRotation += delta;
    Update();
}

glm::vec3 BGLCamera::GetPosition()
{
    return m_eye;
}

glm::vec3 BGLCamera::GetRotation()
{
    return m_rotation;
}

glm::vec3 BGLCamera::GetTargetPosition()
{
    return m_target;
}

float BGLCamera::GetFieldOfView()
{
    return m_fieldOfView;
}

float BGLCamera::GetScreenWidth()
{
    return m_screenWidth;
}

float BGLCamera::GetScreenHeight()
{
    return m_screenHeight;
}

float BGLCamera::GetNearPlane()
{
    return m_nearPlane;
}

float BGLCamera::GetFarPlane()
{
    return m_farPlane;
}

glm::vec3 BGLCamera::GetRotationOfWorld()
{
    return m_worldRotation;
}

glm::mat4 BGLCamera::GetView()
{
    return m_view;
}

glm::mat4 BGLCamera::GetProject()
{
    return m_project;
}

glm::mat4 BGLCamera::GetMVP()
{
    return m_project * m_view;
}